using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

namespace DOTS.DOD.LESSON8
{
    [BurstCompile]
    [RequireMatchingQueriesForUpdate]
    [UpdateInGroup(typeof(MultiCubesMarchSystemGroup))]
    [UpdateAfter(typeof(MultiCubesGenerateSystem))]
    partial struct MultiCubesMarchingSystem : ISystem
    {
        EntityQuery mCubeQuery;

        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            var queryBuilder = new EntityQueryBuilder(Allocator.Temp).WithAll<LocalTransform, CubeSharedComponentData, SharingGroup>();
            //var queryBuilder = new EntityQueryBuilder(Allocator.Temp).WithAll<LocalTransform, CubeComponentData, SharingGroup>();
            mCubeQuery = state.GetEntityQuery(queryBuilder);
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            float deltaTime = SystemAPI.Time.DeltaTime;
            double elapsedTime = SystemAPI.Time.ElapsedTime;
            var generator = SystemAPI.GetSingleton<MultiCubesGenerator>();
            //使用SharedComponent来过滤查询（不推荐使用，使用不当会造成CacheMissing）
            // mCubeQuery.SetSharedComponentFilter(new SharingGroup()
            // {
            //     Group = 1,
            // });
            var cubes = mCubeQuery.ToEntityArray(Allocator.Temp);
            var localTransforms = mCubeQuery.ToComponentDataArray<LocalTransform>(Allocator.Temp);
            for (int i = 0; i < cubes.Length; i++)
            {
                var data = state.EntityManager.GetSharedComponent<CubeSharedComponentData>(cubes[i]);
                //var data = state.EntityManager.GetComponentData<CubeComponentData>(cubes[i]);
                LocalTransform tempTrans = localTransforms[i];

                if (tempTrans.Position.x > generator.CubeTargetPos.x)
                {
                    state.EntityManager.DestroyEntity(cubes[i]);
                }
                else
                {
                    tempTrans.Position +=
                        data.MoveSpeed * deltaTime * new float3(1, (float) math.sin(elapsedTime * 20), 0);
                    tempTrans = tempTrans.RotateY(data.RotateSpeed * deltaTime);
                    localTransforms[i] = tempTrans;
                    state.EntityManager.SetComponentData(cubes[i], localTransforms[i]);
                }
            }

            localTransforms.Dispose();
            cubes.Dispose();
        }
    }
}